﻿using LxBasic;

namespace LxCore
{
    public class AverageStatistic
    {
        public abstract class Base : StatisticBase
        {

        }
        public class Mean : Base
        {
            public override AccumulationDouble RunReport(UserMonitor userMonitor, bool isConsole = false)
            {
                AccumulationDouble totalSum = new AccumulationDouble();
                double totalWeight = 0;
                if (isConsole)
                {

                }
                foreach ((FvInner z, ICellVarArr<double> zf, FvBound b, IFaceVarArr<double> bf) in getSelected(userMonitor, true, true))
                {
                    AccumulationDouble localSum = new AccumulationDouble();
                    double localWeight = 0;
                    if (z != null)
                    {
                        if (zf != null)
                        {
                            MultiThreads.RunParallelTask((tid) =>
                            {
                                Float128 tempSum = 0;
                                (int i1, int endp1) = z.CellIdx.Split(tid);
                                for (; i1 < endp1; i1++)
                                {
                                    tempSum += zf.GetCellVar(i1);
                                }
                                ThreadsMath.MemoryAdd(tempSum);
                            });
                            (double sum1, _, _) = ThreadsMath.MemoryRecallClear();
                            localSum += sum1;
                            localWeight += z.CellIdx.GetCount();
                        }
                        if (isConsole)
                        {

                        }
                    }
                    else if (b != null)
                    {
                        if (bf != null)
                        {
                            MultiThreads.RunParallelTask((tid) =>
                            {
                                Float128 tempSum = 0;
                                (int i1, int endp1) = b.FaceIdx.Split(tid);
                                for (; i1 < endp1; i1++)
                                {
                                    tempSum += bf.GetFaceVar(i1);
                                }
                                ThreadsMath.MemoryAdd(tempSum);
                            });
                            (double sum1, _, _) = ThreadsMath.MemoryRecallClear();
                            localSum += sum1;
                            localWeight += b.FaceIdx.GetCount();
                        }
                        if (isConsole)
                        {

                        }
                    }
                    totalSum += localSum;
                    totalWeight += localWeight;
                }
                if (isConsole)
                {
                    //输出
                }
                return totalSum / totalWeight;
            }
        }

        public class VolumnAve : Base
        {

            public override AccumulationDouble RunReport(UserMonitor userMonitor, bool isConsole = false)
            {
                AccumulationDouble totalSum = new AccumulationDouble();
                double totalWeight = 0;
                if (isConsole)
                {

                }
                foreach ((FvInner z, ICellVarArr<double> zf, FvBound b, IFaceVarArr<double> bf) in getSelected(userMonitor, true, false))
                {
                    AccumulationDouble localSum = new AccumulationDouble();
                    double localWeight = 0;
                    if (z != null)
                    {
                        if (zf != null)
                        {
                            MultiThreads.RunParallelTask((tid) =>
                            {
                                Float128 tempSum = new(), tempW = new();
                                (int i1, int endp1) = z.CellIdx.Split(tid);
                                FvInnCell[] cells = z.InZone.InnCells;
                                for (; i1 < endp1; i1++)
                                {
                                    double v = cells[i1].Volumn;
                                    tempSum += zf.GetCellVar(i1) * v;
                                    tempW += v;
                                }
                                ThreadsMath.MemoryAdd(tempSum, tempW);
                            });
                            (double sum1, double w1, _) = ThreadsMath.MemoryRecallClear();
                            localSum += sum1;
                            localWeight += w1;
                        }
                        if (isConsole)
                        {

                        }
                    }
                    totalSum += localSum;
                    totalWeight += localWeight;
                }
                if (isConsole)
                {
                    //输出
                }
                return totalSum / totalWeight;
            }


        }
        public class AreaAve : Base
        {
            public override AccumulationDouble RunReport(UserMonitor userMonitor, bool isConsole = false)
            {
                AccumulationDouble totalSum = new AccumulationDouble();
                double totalWeight = 0;
                if (isConsole)
                {

                }
                foreach ((FvInner z, ICellVarArr<double> zf, FvBound b, IFaceVarArr<double> bf) in getSelected(userMonitor, false, true))
                {
                    AccumulationDouble localSum = new AccumulationDouble();
                    double localWeight = 0;
                    if (b != null)
                    {
                        if (bf != null)
                        {
                            MultiThreads.RunParallelTask((tid) =>
                            {
                                Float128 tempSum = new(), tempWeight = new();
                                (int i1, int endp1) = b.FaceIdx.Split(tid);
                                var faces = b.InZone.BouFaces;
                                for (; i1 < endp1; i1++)
                                {
                                    double a = faces[i1].Area;
                                    tempSum += bf.GetFaceVar(i1) * a;
                                    tempWeight += a;
                                }
                                ThreadsMath.MemoryAdd(tempSum, tempWeight);
                            });
                            (double sum1, double w1, _) = ThreadsMath.MemoryRecallClear();
                            localSum += sum1;
                            localWeight += w1;
                        }
                        if (isConsole)
                        {

                        }
                    }
                    totalSum += localSum;
                    totalWeight += localWeight;
                }
                if (isConsole)
                {
                    //输出
                }
                return totalSum / totalWeight;
            }
        }
        public class FieldAve : Base
        {

        }
    }
}
//protected override void StatisticThread(FvZone zone, FvBound thread, IField<double> scalar, ThreadInfo threadInfo)
//{
//    Float128 sum = new(), weight = new();
//    var faces = zone.Faces;
//    (int i1, int endp1) = thread.FaceIdx.GetSeg(threadInfo);
//    var sf = scalar.GetFaceField(thread, this);
//    for (; i1 < endp1; i1++)
//    {
//        ref FvFace face = ref faces[i1];
//        sum += (sf.GetFaceValue(i1) * face.Area);
//        weight += (face.Area);
//    }
//    ThreadsMath.MemoryAdd(sum, weight);
//}
//protected override void StatisticZone(FvZone zone, IField<double> scalar, ThreadInfo threadInfo)
//{
//    Float128 sum = new(), weight = new();
//    var cells = zone.Cells;
//    (int i1, int endp1) = zone.Inner.CellIdx.GetSeg(threadInfo);
//    var sf = scalar.GetCellField(zone.Inner, this);
//    for (; i1 < endp1; i1++)
//    {
//        ref FvCell cell = ref cells[i1];
//        sum += (sf.GetCellValue(i1) * cell.Volumn);
//        weight += (cell.Volumn);
//    }
//    ThreadsMath.MemoryAdd(sum, weight);
//}
//public class Average : Base
//{
//    //public override void StatisticCells(IIndexHost cellIdx, ICellVar<double> sf, ICellVar<double> assistant, ThreadInfo threadInfo)
//    //{
//    //    Float128 sum = new(), weight = new();
//    //    (int i1, int endp1) = cellIdx.GetCellIdx().GetTaskIdx(threadInfo);
//    //    for (; i1 < endp1; i1++)
//    //    {
//    //        double tempWeight = assistant.GetCellValue(i1);
//    //        sum += sf.GetCellValue(i1) * tempWeight;
//    //        weight += tempWeight;
//    //    }
//    //    ThreadsMath.MemoryAdd(sum, weight);
//    //}
//    //public override void StatisticFaces(IIndexHost faceIdx, IFaceVar<double> sf, IFaceVar<double> assistant, ThreadInfo threadInfo)
//    //{
//    //    Float128 sum = new(), weight = new();
//    //    (int i1, int endp1) = faceIdx.GetFaceIdx().GetTaskIdx(threadInfo);
//    //    for (; i1 < endp1; i1++)
//    //    {
//    //        double tempWeight = assistant.GetFaceValue(i1);
//    //        sum += (sf.GetFaceValue(i1) * tempWeight);
//    //        weight += tempWeight;
//    //    }
//    //    ThreadsMath.MemoryAdd(sum, weight);
//    //}
//}
//protected double Sum;
//protected double Weight;
//public override void GlobalIni()
//{
//    base.GlobalIni();
//    Sum = 0;
//    Weight = 0;
//}
//public override void LocalFinish()
//{
//    (double sum, double weight, double sum3) = ThreadsMath.MemoryRecallClear();
//    LocalResult = sum / weight;
//    Sum += sum;
//    Weight += weight;
//}

//public override void StatisticCells(IIndexHost cellIdx, ICellVar<double> sf, ICellVar<double> assistant, ThreadInfo threadInfo)
//{
//    Float128 sum = new();
//    (int i1, int endp1) = cellIdx.GetCellIdx().GetTaskIdx(threadInfo);
//    var weight = endp1 - i1;
//    for (; i1 < endp1; i1++)
//    {
//        sum += (sf.GetCellValue(i1));
//    }
//    ThreadsMath.MemoryAdd(sum, weight);
//}
//public override void StatisticFaces(IIndexHost faceIdx, IFaceVar<double> sf, IFaceVar<double> assistant, ThreadInfo threadInfo)
//{
//    Float128 sum = new();
//    (int i1, int endp1) = faceIdx.GetFaceIdx().GetTaskIdx(threadInfo);
//    var weight = endp1 - i1;
//    for (; i1 < endp1; i1++)
//    {
//        sum += (sf.GetFaceValue(i1));
//    }
//    ThreadsMath.MemoryAdd(sum, weight);
//}
//protected override void StatisticZone(FvZone zone, IField<double> scalar, ThreadInfo threadInfo)
//{
//    Float128 sum = new(), weight = new();
//    (int i1, int endp1) = zone.Inner.CellIdx.GetSeg(threadInfo);
//    var sf = scalar.GetCellField(zone.Inner, this);
//    weight += (endp1 - i1);
//    for (; i1 < endp1; i1++)
//    {
//        sum += (sf.GetCellValue(i1));
//    }
//    ThreadsMath.MemoryAdd(sum, weight);
//}
//protected override void StatisticThread(FvZone zone, FvBound thread, IField<double> scalar, ThreadInfo threadInfo)
//{
//    Float128 sum = new(), weight = new();
//    (int i1, int endp1) = thread.CellIdx.GetSeg(threadInfo);
//    var sf = scalar.GetFaceField(thread, this);
//    weight += (endp1 - i1);
//    for (; i1 < endp1; i1++)
//    {
//        sum += (sf.GetFaceValue(i1));
//    }
//    ThreadsMath.MemoryAdd(sum, weight);
//}
//public override void RunStatistic(bool IsConsole)
//{
//    InMonitor.CurrentResult = 0;
//    Sum = 0;
//    Weight = 0;

//}
//protected override void SortOutResult()
//{
//    (double sum, double weight, double sum3) = ThreadsMath.MemoryRecallClear();
//    LocalResult = sum / weight;
//    Sum += sum;
//    Weight += weight;
//    InMonitor.CurrentResult = Sum / Weight;
//}